fix(orchestrator): Keep Claude child work on the child thread - #5456
fix(orchestrator): Keep Claude child work on the child thread#5456mwolson wants to merge 331 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
25de21d to
0af2a6e
Compare
0e1b4fe to
1598863
Compare
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay. You can add or adjust custom eligibility rules. Learn more. |
22bd872 to
a27c1cc
Compare
1598863 to
b5f1b94
Compare
a186d64 to
5b1a115
Compare
b5f1b94 to
9c18ee2
Compare
519c42a to
4c55679
Compare
ea1bb95 to
4c2c69c
Compare
a110e68 to
81c6ac9
Compare
Cancel pending SDK requests before aborting the native session. Preserve per-admission cancellation state and treat stopped initial prompts as interruption instead of provider failure. Finding: R14 prompt cancellation Model: GPT-5.6 Sol via Codex
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection. Finding: P01 nested lineage Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering. Finding: R14 status reconciliation Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups. Finding: P01 bounded history visibility Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls. Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring, pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831 settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted), pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936 video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass, and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2 work-live system. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
a6e0049 to
50a57b6
Compare
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header anchors the active run, the trailing live tool row survives between actions in past tense instead of vanishing, and a shimmering Thinking row marks reasoning gaps. During workspace preparation the header shows "Setting up worktree..." (driven by the local dispatch flag or the v2 run's preparing status, so remote viewers see it too), the composer footer span is gone, and draft promotion waits until the run starts or startup fails instead of navigating mid-preparation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or whitespace-only user message, which renders as an empty bubble under the "Sent by another agent" label. The Claude adapter emitted the opening prompt whenever the subagent was new, and a task_progress frame can register a subagent before any frame carries its prompt, so the message was emitted with the "" default and never rewritten when the real prompt arrived on a later task_started. A shared hasSubagentPromptText guard now gates every subagent opening message. The Claude adapter emits it the first time the task prompt actually has text rather than on first registration, so a late prompt still opens the child thread exactly once. Codex's existing length check becomes trim-aware, and Cursor and ACP pick up the same guard.
ed223fe to
ac5be27
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ac5be27. Configure here.
ceea97b to
d2f1f51
Compare

What Changed
A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.
A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.
Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.
Why
Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.
The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.
Review both here. #5388 claude-postsettle-attribution is closed as absorbed.
UI Changes
Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.
No before/after screenshots.
Checklist
Note
Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.
Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared
hasSubagentPromptTextguard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. aftertask_progressbeforetask_started).Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an
emitPromptMessageflag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on staletask_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.A replay fixture and unit tests cover blank prompts and late prompt arrival.
Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Keep Claude child work on the child thread, gate empty subagent prompts
hasSubagentPromptTextin SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn itemsregisterSessionSubagentin ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)bufferWakeMessageto attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites thetool_resulthandling loop to correctly resolve subagents bytool_use_idortask_id, buffer messages for unregistered Agent launches, and skip failed-successor tasksclaude_subagent_empty_promptcovering a blank prompt, a whitespace-only prompt, and a late-arriving promptMacroscope summarized ac5be27.